package com.zxjbyte.yiyi.module.upms.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SmUtil;
import com.zxjbyte.yiyi.framework.common.constant.Constant;
import com.zxjbyte.yiyi.framework.common.domain.api.PageResult;
import com.zxjbyte.yiyi.framework.common.util.AuthUtil;
import com.zxjbyte.yiyi.framework.mybatis.service.impl.BaseServiceXImpl;
import com.zxjbyte.yiyi.framework.mybatis.util.UniqueChecker;
import com.zxjbyte.yiyi.module.system.api.devconfig.DevConfigApi;
import com.zxjbyte.yiyi.module.system.api.dict.DictCacheApi;
import com.zxjbyte.yiyi.module.system.enums.DevConfigKeyEnum;
import com.zxjbyte.yiyi.module.system.enums.DictCodeEnum;
import com.zxjbyte.yiyi.module.upms.convert.UserConvert;
import com.zxjbyte.yiyi.module.upms.domain.entity.UserPO;
import com.zxjbyte.yiyi.module.upms.domain.param.UserAddParam;
import com.zxjbyte.yiyi.module.upms.domain.param.UserListParam;
import com.zxjbyte.yiyi.module.upms.domain.param.UserUpdateParam;
import com.zxjbyte.yiyi.module.upms.domain.vo.UserDetailVO;
import com.zxjbyte.yiyi.module.upms.domain.vo.UserListVO;
import com.zxjbyte.yiyi.module.upms.mapper.UserMapper;
import com.zxjbyte.yiyi.module.upms.messaging.eventbus.publisher.UserEventPublisher;
import com.zxjbyte.yiyi.module.upms.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import static com.zxjbyte.yiyi.framework.common.util.ValidationUtil.*;

/**
 * @Author zhangxingjia
 * @Date 2024/9/9 19:39
 * @Version: 1.0
 */
@Service
public class UserServiceImpl extends BaseServiceXImpl<UserMapper, UserPO> implements UserService {

    @Resource
    private DictCacheApi dictCacheApi;
    @Resource
    private DevConfigApi devConfigApi;
    @Resource
    private UserEventPublisher eventPublisher;

    @Override
    public PageResult<UserListVO> list(UserListParam param) {
        return null;
    }

    @Override
    public UserDetailVO detail(Long id) {
        UserPO userPo = checkUserInfo(id);
        return UserConvert.INSTANCE.poToDetailVo(userPo);
    }

    @Override
    public void addUser(UserAddParam addParam) {
        // 参数校验
        checkParam(null, addParam);
        UserPO userPo = UserConvert.INSTANCE.addParamToPo(addParam);
        userPo.setTenantId(AuthUtil.getTenantId());
        userPo.setSalt(IdUtil.fastSimpleUUID());
        userPo.setPassword(sm3Hash(userPo.getPassword(), userPo.getSalt()));
        save(userPo);
        eventPublisher.publishUserCreateEvent(userPo);
    }

    @Override
    public void updateUser(UserUpdateParam updateRequest) {
        // 参数校验
        checkParam(updateRequest.getId(), updateRequest);
        // 编辑用户信息校验
        UserPO userPo = checkUserInfo(updateRequest.getId());
        UserConvert.INSTANCE.updatePoFromParam(userPo, updateRequest);
        userPo.setPassword(sm3Hash(userPo.getPassword(), userPo.getSalt()));
        updateById(userPo);
        eventPublisher.publishUserUpdateEvent(userPo);
    }

    @Override
    public void deleteUser(Long id) {

    }

    private void checkParam(Long id, UserAddParam param){
        if(param.getIdType() != null){
            assertFalse(!dictCacheApi.getDictItemValueAsInt(DictCodeEnum.SYS_USER_ID_TYPE).contains(param.getIdType()), "请选择正确的证件类型");
            assertNotBlank(param.getIdNo(), () -> "请填写证件号码");
        }
        // 账号唯一校验
        assertTrue(UniqueChecker.of(this).where(UserPO::getAccount, param.getAccount()).ignoreId(id).check(), "用户账号已存在");
        // 手机号唯一校验
        assertTrue(UniqueChecker.of(this).where(UserPO::getPhone, param.getPhone()).ignoreId(id).check(), "用户手机号已存在");
    }

    private UserPO checkUserInfo(Long id) {
        UserPO userPo = null;
        assertFalse(id != null && (userPo = getById(id)) == null, "用户不存在");
        return userPo;
    }

    /**
     * 密码国密加密
     * @param password
     * @param salt
     * @return
     */
    private String sm3Hash(String password, String salt){
        // 密码为空使用默认密码 admin_yy
        password = StrUtil.isEmpty(password) ? devConfigApi.getConfigValue(DevConfigKeyEnum.DEFAULT_USER_PASSWORD) : password;
        return SmUtil.sm3WithSalt(salt.getBytes(Constant.CHARSET_UTF_8)).digestHex(password);
    }
}
